package com.cctv.kvtest;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created By Mahongyin
 * Date    2021/9/10 8:53
 */

public class MyThreadPool extends ThreadPoolExecutor {

    public interface Callback {
        void before(Thread t, Runnable r);

        void after(Runnable r, Throwable t);

        void terminat();
    }

    private static Callback callback;

    private static int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static int MAXIMUN_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static int KEEP_LIVE = 30;//S
    private static MyThreadPool threadPool;

    private MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    private MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
    }

    private static final ThreadFactory tf = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            return new Thread(r, "CNThreadPool #" + mCount.getAndIncrement());
        }
    };

    public static MyThreadPool getInstance() {
        if (threadPool == null) {
            synchronized (MyThreadPool.class) {
                if (threadPool == null) {
                    threadPool = new MyThreadPool(CORE_POOL_SIZE, MAXIMUN_POOL_SIZE, KEEP_LIVE,
                            TimeUnit.SECONDS,
                            // new LinkedBlockingDeque<Runnable>(128));
                            new LinkedBlockingQueue<>(128), tf);
                    //核心线程也设置超时
                    threadPool.allowCoreThreadTimeOut(true);
                }
            }
        }
        return threadPool;
    }

    public static MyThreadPool getInstance(Callback mCallback) {
        //  么 ？？
        if (mCallback != null) {
            callback = mCallback;
        }
        return getInstance();
    }

    public void run(Runnable runnable) {
        threadPool.execute(runnable);
    }
    public void stop(){
        threadPool.shutdownNow();
    }

    @Override
    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        if (callback != null) {
            callback.before(t, r);
        }
    }

    @Override
    protected void afterExecute(Runnable r, Throwable t) {
        super.afterExecute(r, t);
        if (callback != null) {
            callback.after(r, t);
        }
    }

    @Override
    protected void terminated() {
        super.terminated();
        if (callback != null) {
            callback.terminat();
        }
        //shutdown
    }
}
